package com.handu.luna.boss.controller.support;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.handu.luna.boss.controller.BaseController;
import com.handu.luna.boss.controller.BossModel;
import com.handu.luna.core.domain.Session;
import com.handu.luna.core.domain.admin.AdminControllerDescription;
import com.handu.luna.core.domain.admin.Operator;
import com.handu.luna.core.domain.admin.WorkLog;
import com.handu.luna.core.domain.support.EnumAwareConvertUtilsBean;

public class PermissionInterceptor extends HandlerInterceptorAdapter {
	protected Log logger = LogFactory.getLog(this.getClass());
	
	public static final String SESSION_ID_FLAG = "luna_session_id";
	public static final String LOGIN_URL = "/login/";
	public static final String LOGIN_VALID_URL = "/login/valid";
	public static final int SESSION_TIMEOUT = 60*60;
	
	@Autowired
	private Session sessionService;

	
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		BeanUtilsBean.setInstance(new BeanUtilsBean(new EnumAwareConvertUtilsBean()));
		if(handler instanceof HandlerMethod || handler instanceof BaseController){
			String sessionId = getSessionId(request,response);
			Session session = sessionService.getOrCreateSession(sessionId);
			if(request.getRequestURI().endsWith(LOGIN_URL) || request.getRequestURI().endsWith(LOGIN_VALID_URL)){
				if(sessionId == null){
					setCookie(response,sessionService.getOrCreateSession(null).getId());
				}
				try{
					if(handler instanceof HandlerMethod){
						HandlerMethod method = (HandlerMethod)handler;
						setValue(method.getBean(),session,null);
					}
				}catch(Exception e){
					logger.debug("set session error",e);
				}
			}else{
				if(sessionId == null){
					response.sendRedirect(LOGIN_URL);
					return false;
				}
				Operator currentOperator = session.getOperator();
				if(currentOperator == null){
					response.sendRedirect(LOGIN_URL);
					return false;
				}else{
					if(handler instanceof HandlerMethod){
						HandlerMethod method = (HandlerMethod)handler;
						setValue(method.getBean(),session,currentOperator);
					}else if (handler instanceof BaseController){
						setValue(handler,session,currentOperator);
					}
				}
				checkPermission(currentOperator);			
			}
		
		}
		return true;
	}
	
	
	
	
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		Operator operator = null;
		BaseController controller = null;
		if(handler instanceof HandlerMethod){
			HandlerMethod method = (HandlerMethod)handler;
			controller = (BaseController)method.getBean();
			
		}else if (handler instanceof BaseController){
			controller = (BaseController)handler;
			operator = controller.getOperator();
		}
		if(controller != null && controller.getOperator() != null)operator = controller.getOperator();
		String operatorName =  (operator == null ? "无记录" : operator.getName());
		long operatorId = (operator == null ? 0 : operator.getId());
		String ip = request.getRemoteAddr();
		String url = request.getRequestURI();
		String method = request.getMethod();
		String content = "";
		if(modelAndView != null){
			Object descObj =modelAndView.getModel().getOrDefault(BossModel.CONTROLLER_DESCRIPTION_FLAG,null);
			if(descObj != null &&  descObj instanceof AdminControllerDescription){
				AdminControllerDescription desc = (AdminControllerDescription)descObj;
				content += desc.getCategory().getName() + " ";
			}
			content += "\t";
			content += modelAndView.getModel().getOrDefault(BossModel.ACTION_DESCRIPTION_FLAG, "");
		}
		new WorkLog().log(operatorName, operatorId, ip, content,url,method);
		super.postHandle(request, response, handler, modelAndView);
	}




	private void setValue(Object _controller,Session session,Operator currentOperator){
		BaseController controller = (BaseController)_controller;
		controller.setSession(session);
		controller.setOperator(currentOperator);
	}

	/**
	 * 返回session id，如果第一次访问或异常访问则返回null
	 * @param request HttpServletRequest
	 * @return  返回session id，如果第一次访问或异常访问则返回null
	 */
	private String getSessionId(HttpServletRequest request, HttpServletResponse response){
		String sessionId = null;
		
		Cookie[] cookies =  request.getCookies();
		if(cookies != null){
			for(Cookie cookie : cookies){
				if(cookie.getName().equals(SESSION_ID_FLAG) ){
					sessionId = cookie.getValue();
					setCookie(response,sessionId);
				}
			}
		}
		return sessionId;
	}

	/**
	 * 设置用户会话cookie
	 * TODO: 这里存在一个问题，用户可以自行修改cookie过期时间。不过由于cookie机制的安全性，一般认为不是大问题。作为未来改进点。
	 * @param response
	 * @param sessionId
	 */
	private void setCookie(HttpServletResponse response,String sessionId){
		Cookie cookie = new Cookie(SESSION_ID_FLAG,sessionId);
		cookie.setPath("/");
		cookie.setMaxAge(SESSION_TIMEOUT);
		response.addCookie(cookie);
	}
	
	private void checkPermission(Operator currentOperator){
		
	}
}
